#include <iostream>
#include <sys/socket.h>
#include <netdb.h>
#include <cstdio>
#include <unistd.h>
#include <cstdlib>
#include <arpa/inet.h>
#include <cstring>

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        std::cout << "Usage: ./client 服务端ip 服务端port" << std::endl;
        return -1;
    }

    // 1、创建客户端的socket
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1)
    {
        std::cout << "socket error" << std::endl;
        return -1;
    }

    // 2、向服务器发起连接请求
    struct hostent* h;   // 用于储存服务端ip的数据结构
    h = gethostbyname(argv[1]);
    if (h == 0)
    {
        std::cout << "gethostbyname failed" << std::endl;
        close(sockfd);
        return -1;
    }
    struct sockaddr_in serveraddr;  //存放服务端ip和端口的结构体
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    memcpy(&serveraddr.sin_addr, h->h_addr, h->h_length);  // 指定服务端的ip
    // serveraddr.sin_addr.s_addr = inet_addr(argv[1]);   // 指定服务端的ip，只能用ip，不能用域名和主机名
    serveraddr.sin_port = htons(std::atoi(argv[2]));  // 指定服务端的port

    int connectId = connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
    if (connectId != 0)
    {
        std::cout << "connect err!" << std::endl;
        return -1;
    }

    // 3、与服务器通讯，客户发送一个请求报文后等待服务端的回复，收到回复后，再发下一个请求报文
    char buffer[1024];
    for (int i = 0; i < 3; i++)
    {
        int retIndex;
        memset(buffer, 0, sizeof(buffer));
        sprintf(buffer, "这是第%d个发送报文，编号%03d", i+1, i+1);   // 发送报文的内容

        retIndex = send(sockfd, buffer, strlen(buffer), 0);
        if (retIndex <= 0)
        {
            perror("send");
            break;
        }
        std:: cout << "发送:" << buffer << std::endl;

        memset(buffer, 0, sizeof(buffer));
        // 接受服务端的回应报文，如果服务端没有发送回应报文，recv()函数阻塞等待
        retIndex = recv(sockfd, buffer, sizeof(buffer), 0);
        if (retIndex <= 0)
        {
            std::cout << "retIndex=" << retIndex << std::endl;
            break;
        }
        std::cout << "接收:" << buffer << std::endl;

        sleep(1);
    }

    // 4、关闭socket，释放资源
    close(sockfd);
    
}

